#ifndef __CONCURRENTALLOC_H__
#define __CONCURRENTALLOC_H__

#include "threadCache.h"
#include "pageCache.h"

static void* cAlloc(size_t size)
{
  try 
  {
    if(size >= MAX_BYTES)
    {
      size_t actual_size = SizeClass::getRoundUp(size);
      Span* sp = PageCache::getInstance()->getSpan(actual_size >> PAGE_SHIFT);
      sp->size_ = actual_size;
      void* ptr = (void*)(sp->pageid_ << PAGE_SHIFT);
      return ptr;
    }
    else 
    {

      if(tls_threadcache == nullptr)
      {
        //tls_threadcache = new ThreadCache;
        tls_threadcache = reinterpret_cast<ThreadCache*>(SystemAlloc(sizeof(ThreadCache)));
        new (tls_threadcache) ThreadCache();
      }
      return tls_threadcache->Allocate(size);
    }

  }
  catch (std::exception& c)
  {
    std::cout << c.what() << std::endl;
  }
  return nullptr;
}


static void cFree(void* ptr)
{
  if(ptr == nullptr)
    return;
  Span* sp = PageCache::getInstance()->getSpanByPageId(ptr);
  size_t size = sp->size_;
  try 
  {
    if(size >= MAX_BYTES)
    {
      //归还给系统
      PageCache::getInstance()->releaseSpanToPageCache(sp);
    }
    else 
    {
      assert(ptr);
      tls_threadcache->Deallocate(ptr, size);
    }
  }
  catch(std::exception& c)
  {
    std::cout << c.what() << std::endl;
  }
}

template<class T>
static T* Alloc(T tmp)
{
  size_t size = sizeof(tmp);
  try 
  {
    if(size >= MAX_BYTES)
    {
      //向pageCache申请
      //获得实际需要的内存大小，会向上对齐
      size_t actual_size = SizeClass::getRoundUp(size);

      Span* sp = PageCache::getInstance()->getSpan(actual_size >> PAGE_SHIFT);
      sp->size_ = actual_size;
      T* ptr = (T*)(sp->pageid_ << PAGE_SHIFT);
      new (ptr) T();
      return ptr;
    }
    else 
    {
      if(tls_threadcache == nullptr)
      {
        tls_threadcache = (ThreadCache*)SystemAlloc(sizeof(ThreadCache));
        new (tls_threadcache) ThreadCache();
        //tls_threadcache = new ThreadCache;
      }
      return (T*)tls_threadcache->Allocate(size);

    }
  }
  catch(std::exception& c)
  {
    std::cout << "cAlloc fail"  << c.what() << std::endl;
  }
}


template<class T>
static void Free(T* ptr)
{
  if(ptr == nullptr)
    return;
  Span* sp = PageCache::getInstance()->getSpanByPageId(ptr);
  size_t size = sp->size_;
  try 
  {
    if(size >= MAX_BYTES)
    {
      //归还给pageCache
      PageCache::getInstance()->releaseSpanToPageCache(sp);
    }
    else 
    {
		assert(tls_threadcache);
      ptr->~T();
      tls_threadcache->Deallocate(ptr, size);
    }
  }
  catch(std::exception& c)
  {
    std::cout << "cFree fail"  << c.what() << std::endl;
  }
}



#endif
